package cool.taomu.software.fig.utils

import com.google.gson.Gson
import com.sun.management.OperatingSystemMXBean
import java.lang.management.ManagementFactory
import java.lang.management.MemoryUsage
import java.util.HashMap
import java.util.Map
import java.util.TreeMap
import org.eclipse.xtend.lib.annotations.Accessors
import org.eclipse.xtend.lib.annotations.ToString

class RuntimeStateUtils {
    @Accessors
    @ToString
    static class RuntimeState {
        String osName;
        long freePhysicalMemorySize;
        long totalPhysicalMemorySize
        long UsePhysicalMemorySize;
        long totalSwapSpaceSize;
        long freeSwapSpaceSize
        long UseSwapSpaceSize
        long availableProcessors;
        double systemLoadAverage;
        double systemCpuLoad;
        JvmInfo jvmInfo;
    }

    @Accessors
    @ToString
    static class JvmInfo {
        String jvmName;
        long vmFree;
        long vmUse;
        long vmTotal;
        long vmMax;
        String runtimeArguments;
        ClassLoaderInfo classLoaderInfo;
        ThreadInfo threadInfo;
        JvmMemoryInfo memoryInfo;
    }

    @Accessors
    @ToString
    static class ThreadInfo {
        long threadCount;
        long currentThreadCpuTime;
        long currentThreadUserTime;
    }

    @Accessors
    @ToString
    static class ClassLoaderInfo {
        /**
         * 获取当前JVM加载的类数量
         */
        long LoadedClassCount;
        /**
         *  获取JVM总加载的类数量
         */
        long TotalLoadedClassCount;
        /**
         * 获取JVM卸载的类数量
         */
        long UnloadedClassCount;
    }

    @Accessors
    @ToString
    static class JvmMemoryInfo {
        // MemoryUsage 含义包括初始大小，最大大小，已使用大小等，单位字节
        // 获取堆内存使用情况，
        MemoryUsage heapMemoryUsage;
        // 获取堆外内存使用情况。
        MemoryUsage nonHeapMemoryUsage;
        Map<String, MemoryUsage> heapInfo = new HashMap<String, MemoryUsage>();
    }

    def getRuntimeState() {
        var osinfo = new RuntimeState();
        var osmxb = ManagementFactory.getOperatingSystemMXBean() as OperatingSystemMXBean;
        // 操作系统的版本
        osinfo.osName = #[
            System.getProperty("os.name"),
            System.getProperty("os.version"),
            System.getProperty("os.arch")
        ].join(" ");
        // 操作系统物理内存已用的空间为
        osinfo.freePhysicalMemorySize = osmxb.getFreePhysicalMemorySize();
        // 操作系统总物理内存
        osinfo.totalPhysicalMemorySize = osmxb.getTotalPhysicalMemorySize();
        // 操作系统物理内存的空闲空间为
        if (osinfo.totalPhysicalMemorySize !== 0L) {
            osinfo.UsePhysicalMemorySize = osinfo.totalPhysicalMemorySize - osinfo.freePhysicalMemorySize;
        }
        osinfo.availableProcessors = osmxb.availableProcessors;
        osinfo.systemLoadAverage = osmxb.systemLoadAverage;
        osinfo.systemCpuLoad = osmxb.systemCpuLoad;
        osinfo.totalSwapSpaceSize = osmxb.totalSwapSpaceSize
        osinfo.freeSwapSpaceSize = osmxb.freeSwapSpaceSize;
        if(osinfo.totalSwapSpaceSize !== 0){
            osinfo.UseSwapSpaceSize = osinfo.totalSwapSpaceSize - osinfo.freeSwapSpaceSize;
        }
        osinfo.jvmInfo = jvmInfo();
        return osinfo;
    }

    private def jvmInfo() {
        var jvm = new JvmInfo();
        var Runtime rt = Runtime.getRuntime();
        // JVM总内存空间为
        jvm.vmTotal = rt.totalMemory();
        // JVM内存的空闲空间为
        jvm.vmFree = rt.freeMemory();
        // JVM总内存空间为
        jvm.vmMax = rt.maxMemory();
        // JVM内存已用的空间为
        jvm.vmUse = jvm.vmTotal - jvm.vmFree;
        var vmname = System.getProperty("java.vm.name");
        var vmversion = System.getProperty("java.vm.version");
        var vmvendor = System.getProperty("java.vm.vendor");
        jvm.jvmName = #[vmname, vmvendor, vmversion].join(" ");
        var runtimeMXBean = ManagementFactory.getRuntimeMXBean();
        jvm.runtimeArguments = runtimeMXBean.getInputArguments().join(",");
        // 类加载器信息
        var classLoadingMXBean = ManagementFactory.getClassLoadingMXBean();
        var classLoaderInfo = new ClassLoaderInfo();
        // 获取当前JVM加载的类数量
        classLoaderInfo.LoadedClassCount = classLoadingMXBean.getLoadedClassCount();
        // 获取JVM总加载的类数量
        classLoaderInfo.TotalLoadedClassCount = classLoadingMXBean.getTotalLoadedClassCount();
        // 获取JVM卸载的类数量
        classLoaderInfo.UnloadedClassCount = classLoadingMXBean.getUnloadedClassCount();
        jvm.classLoaderInfo = classLoaderInfo;
        // jvm线程消息
        var threadMXBean = ManagementFactory.getThreadMXBean();
        // 获取当前JVM内的线程数量，该指标非常重要。
        // 之前遇到过用为没有对该指标进行监控而导致问题无法及时定位的情况。
        var threadInfo = new ThreadInfo();
        threadInfo.threadCount = threadMXBean.getThreadCount();
        threadInfo.currentThreadCpuTime = threadMXBean.getCurrentThreadCpuTime();
        threadInfo.currentThreadUserTime = threadMXBean.getCurrentThreadUserTime();
        jvm.threadInfo = threadInfo;
        jvm.memoryInfo = getMemoryInfo();
        return jvm;
    }

    private def getMemoryInfo() {
        val memInfo = new JvmMemoryInfo();
        var memoryMXBean = ManagementFactory.getMemoryMXBean();
        memInfo.heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
        memInfo.nonHeapMemoryUsage = memoryMXBean.getNonHeapMemoryUsage();
        var memoryPoolMXBeans = ManagementFactory.getMemoryPoolMXBeans();
        memoryPoolMXBeans.forEach [ info |
            memInfo.heapInfo.put(info.name, info.usage)
        ]
        return memInfo;
    }

    def static getInfo() {
        var sortMap = new TreeMap<Object, Object>([str1, str2|(str1 as String).compareTo(str2 as String)]);
        sortMap.putAll(System.getProperties().immutableCopy);
        return sortMap;
    }

    def static void main(String[] args) {
        var a = new RuntimeStateUtils();
        var r = new Gson().toJson(a.getRuntimeState());
        println(r);
        println(new Gson().fromJson(r, RuntimeState));
    }

}
